#include "Model.h"
#include "GraphicManager.h"
#include <cassert>
#include <math.h>

#include <iostream>

using namespace std;

Model::Model(std::string modelName):VBOIDs(NULL),
									m_frame(0.f)
{
	m_Data = GraphicManager::Istance()->GetModelData(modelName);
	m_model = m_Data->Model;
	
	
	//We make a copy, in that way we can just change texture using a single model.
	VBOIDs = new VBOID[m_Data->TotalMesh];
	for(int i=0;i<m_Data->TotalMesh;i++)
	{
		VBOIDs[i] = m_Data->VBOIDs[i];
	}

	
}

Model::~Model()
{

}

void Model::RenderMesh( int mesh, GLuint shader /* = 0 */)
{
	glPushMatrix();
	//if(shader == 0) glMultMatrixf( (GLfloat*) VBOIDs[mesh].MeshMatrix );

	if (!VBOIDs[mesh].TwoSides)
	{
		glEnable(GL_CULL_FACE);
		glCullFace(GL_BACK);
	}

	if(shader == 0) //use base shader
	{
		//Use base if mesh is not texturized, baseTextured otherwise.
		glUseProgramObjectARB(GraphicManager::Istance()->GetShader( (VBOIDs[mesh].TextureID) ? "baseTextured" : "base"  ));
	}

	glEnableVertexAttribArrayARB(0);
	if(VBOIDs[mesh].NormalID)
		glEnableVertexAttribArrayARB(2);
	if(VBOIDs[mesh].TextureID)
	{
		glEnable(GL_TEXTURE_2D);
		glEnableVertexAttribArrayARB(8);
	}

	glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOIDs[mesh].VerticeID );
	glVertexAttribPointerARB(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
	if(VBOIDs[mesh].NormalID)
	{
		glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOIDs[mesh].NormalID );
		glVertexAttribPointerARB(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

	}

	if(VBOIDs[mesh].TextureID)
	{
		glBindTexture(GL_TEXTURE_2D, VBOIDs[mesh].TextureID);
		glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOIDs[mesh].TexCoordID );
		glVertexAttribPointerARB(8, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
	}

	if(VBOIDs[mesh].TrianglesArray ) glDrawArrays( GL_TRIANGLES, 0, VBOIDs[mesh].VerticeNum );
	else glDrawArrays( GL_POLYGON, 0, VBOIDs[mesh].VerticeNum );

	glDisableVertexAttribArrayARB(0);
	if(VBOIDs[mesh].NormalID)
		glDisableVertexAttribArrayARB(2);
	if(VBOIDs[mesh].TextureID)
	{
		glDisable(GL_TEXTURE_2D);	
		glDisableVertexAttribArrayARB(8);
	}
	
	if(shader == 0)	glUseProgramObjectARB(0);

	if(!VBOIDs[mesh].TwoSides)	glDisable(GL_CULL_FACE);

	glPopMatrix();

	glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );


}

void Model::RenderMeshs(GLuint shader /* = 0 */)
{
	for (int i = 0; i < m_Data->TotalMesh ; ++i)
	{
		RenderMesh(i,shader);
	}
}

void Model::Draw(const sf::Vector2f& offset, const sf::Vector2f& facing)
{
	
	glPushMatrix();
	
	//Identical(correct en?=P) Matrix
	GLfloat matrix[] = {1.f, 0.f, 0.f, 0.f, 
		0.f, 1.f, 0.f, 0.f, 
		0.f, 0.f, 1.f, 0.f, 
		0.f, 0.f, 0.f, 1.f};


	//rotation on Y
	matrix[0] = facing.y;
	matrix[10] = facing.y;		

	if (facing.x != 0.f)
	{
		matrix[2] = -facing.x;
		matrix[8] = facing.x;
	}

	//Traslation offset
	matrix[12] = offset.x;
	matrix[14] = offset.y;

	glMultMatrixf(matrix);

	RenderMeshs();

	glPopMatrix();
}